<!doctype html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport"
          content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>粒子背景效果高级</title>
    <style>
      canvas{
        position: fixed;
        left: 0;
        top: 0;
        background: #222;
        width: 100%;
        height: 100%;
      }
    </style>

</head>

<body>
    <canvas></canvas>
</body>
<script>
    const cvs=document.querySelector('canvas');
    const ctx=cvs.getContext('2d');
    function init(){
        cvs.width=window.innerWidth*devicePixelRatio;
        cvs.height=window.innerHeight*devicePixelRatio;
    }
    init();
    
    /**
     *返回min,max范围内的随机数
     */
    function getRandom(min,max){
        return Math.floor(Math.random()*(max+1-min)+min);
    }

    //定义小球
    class Point{
        constructor(){
            this.r=6;
            this.x=getRandom(0,cvs.width-this.r/2);
            this.y=getRandom(0,cvs.height-this.r/2);
            this.xSpeed=getRandom(-50,50);
            this.ySpeed=getRandom(-50,50);
            this.lastDrawTime=null;
        }
        draw(){
            //更新坐标
            if(this.lastDrawTime){
                //计算新坐标
                const duration=((Date.now()-this.lastDrawTime)/1000);
                //距离
                const xDis=this.xSpeed*duration;
                const yDis=this.ySpeed*duration;

                //新坐标
                let x=this.x+xDis
                let y=this.y+yDis
                if(x>cvs.width-this.r/2){
                    x=cvs.width-this.r/2;
                    this.xSpeed=-this.xSpeed;
                }else if(x<0){
                    x=0;
                    this.xSpeed=-this.xSpeed;
                }
                if(y>cvs.height-this.r/2){
                    y=cvs.height-this.r/2;
                    this.ySpeed=-this.ySpeed;
                }else if(y<0){
                    y=0;
                    this.ySpeed=-this.ySpeed;

                }
                this.x=x;
                this.y=y;

            }
            ctx.beginPath();
            ctx.arc(this.x,this.y,this.r,0,2*Math.PI);
            ctx.fillStyle='rgb(200,200,200)';
            ctx.fill();
            this.lastDrawTime=Date.now();
        }
    }

    class Graph{
        
        constructor(pointNumber=120,maxDis=200){
            //创建一个数组，里面包含两百个point对象
            this.points=new Array(pointNumber).fill(0).
            map(()=>new Point());
            this.maxDis=maxDis;
        }
        draw(){
            requestAnimationFrame(()=>{
                this.draw();
            })
            ctx.clearRect(0,0,cvs.width,cvs.height);
            for(let i=0;i<this.points.length;i++){
                const p1=this.points[i];
                p1.draw();
                for(let j=i+1;j<this.points.length;j++){
                    const p2=this.points[j];
                    // 使用勾股定理计算过两点之间的距离
                    const d=Math.sqrt((p1.x-p2.x)**2+(p1.y-p2.y)**2)
                    if(d>this.maxDis){
                        continue;
                    }
                    ctx.beginPath();
                    ctx.moveTo(p1.x,p1.y);
                    ctx.lineTo(p2.x,p2.y);
                    ctx.closePath();
                    ctx.strokeStyle=`rgba(200,200,200,${1-d/this.maxDis})`;
                    // ctx.strokeStyle=`rgba(200,200,200,.01)`;

                    ctx.stroke();
                }
            }
        }
    }
    const g=new Graph();
    g.draw()

</script>




